package com.word;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;

/**
 * PDF工具类：通过Jacob实现
 * 1、Word文档转PDF
 * 2、PDF裁剪
 * 3、PDF转BufferedImage
 */
public class JacobUtil {

    private static final Integer WORD_TO_PDF_OPERAND = 17;
    private static final Integer EXCEL_TO_PDF_OPERAND = 0;

    /**
     * word文档转PDF：支持doc、docx
     * @param source    word路径
     * @param target    PDF保存路径
     * @return  是否转换成功(异常即失败)
     */
    public static boolean word2pdf(String source, String target) {
        ActiveXComponent app = null;
        try {
            app = new ActiveXComponent("Word.Application");
            app.setProperty("Visible", false);
            Dispatch docs = app.getProperty("Documents").toDispatch();
            Dispatch doc = Dispatch.call(docs, "Open", source, false, true).toDispatch();
            File tofile = new File(target);
            if (tofile.exists()) {
                tofile.delete();
            }
            Dispatch.call(doc, "SaveAs", target, WORD_TO_PDF_OPERAND);
            Dispatch.call(doc, "Close", false);
            return true;
        } catch (Exception e) {
            System.out.println("Word转PDF出错：" + e.getMessage());
            return false;
        } finally {
            if (app != null) {
                app.invoke("Quit", EXCEL_TO_PDF_OPERAND);
            }
        }
    }

    /**
     * PDF裁剪：循环对PDF页进行裁剪
     * @param source    PDF源路径
     * @param reduceLowerLeftX  左下X轴裁剪长度
     * @param reduceLowerLeftY  左下Y轴裁剪长度
     * @param reduceUpperRightX 右上X轴裁剪长度
     * @param reduceUpperRightY 右上Y轴裁剪长度
     * @return  裁剪后的PDF输出流
     */
    public static ByteArrayOutputStream crop(String source,float reduceLowerLeftX,float reduceLowerLeftY,float reduceUpperRightX,float reduceUpperRightY) {
        PDDocument targetDoc = null;
        ByteArrayOutputStream baos = null;
        try (PDDocument sourceDoc = PDDocument.load(new File(source))) {
            targetDoc = new PDDocument();
            Iterator<PDPage> pageIterator = sourceDoc.getDocumentCatalog().getPages().iterator();
            PDPage pdPage = null;
            PDRectangle cropBox = null;
            while(pageIterator.hasNext()){
                pdPage = pageIterator.next();
                cropBox = pdPage.getCropBox();
                cropBox.setLowerLeftX(cropBox.getLowerLeftX()+reduceLowerLeftX);
                cropBox.setLowerLeftY(cropBox.getLowerLeftY()+reduceLowerLeftY);
                cropBox.setUpperRightX(cropBox.getUpperRightX()-reduceUpperRightX);
                cropBox.setUpperRightY(cropBox.getUpperRightY()-reduceUpperRightY);
                pdPage.setCropBox(cropBox);
                targetDoc.addPage(pdPage);
            }
            baos = new ByteArrayOutputStream();
            targetDoc.save(baos);
            targetDoc.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return baos;
    }

    /**
     * 加载PDF，并转成BufferedImage列表
     * @param is    PDF输入流
     * @param dpi   加载使用的dpi
     * @return  PDF每页的BufferedImage
     */
    public static List<BufferedImage> loadPdf(InputStream is, float dpi) {
        List<BufferedImage> bufferedImages = null;
        try(PDDocument sourceDoc = PDDocument.load(is)){
            if(sourceDoc==null)return null;
            bufferedImages = new LinkedList<>();
            int pageSize = sourceDoc.getNumberOfPages();
            PDFRenderer renderer = new PDFRenderer(sourceDoc);
            BufferedImage bufferedImage = null;
            for(int i=0;i<pageSize;i++){
                bufferedImage = renderer.renderImageWithDPI(i, dpi, ImageType.GRAY);
                bufferedImages.add(bufferedImage);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        return bufferedImages;
    }

    /**
     * 加载PDF，并转成BufferedImage列表
     * @param source   PDF所在路径
     * @param dpi   加载使用的dpi
     * @return  PDF每页的BufferedImage
     */
    public static List<BufferedImage> loadPdf(String source,float dpi){
        try {
            return loadPdf(new FileInputStream(source),dpi);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static float reduceX = 30,reduceY0=70,reduceY1=65;

    public static void main(String[] args) throws Exception {
        reduceX=30;
        reduceY0=70;
        reduceY1=70;
        String clauseCode = "1005002_4";
        String source = "D:/poi/clause/"+clauseCode+".doc";
        String target = "D:/poi/clause/"+clauseCode+".pdf";
        String gifDirectory = "D:/poi/clause/bat//"+clauseCode+"/";
        String gifFormatName = clauseCode+"_%02d.gif";
        StringBuilder printPath = new StringBuilder();
        StringBuilder jarPath = new StringBuilder();

        long start = System.currentTimeMillis();
        word2pdf(source,target);
        System.out.println("Word转PDF耗时："+(System.currentTimeMillis()-start));
        ByteArrayOutputStream baos = crop(target,reduceX,reduceY0,reduceX,reduceY1);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        List<BufferedImage> bufferedImages = loadPdf(bais,210);
        System.out.println("载入PDF耗时："+(System.currentTimeMillis()-start));
        GifUtil.pdf2GifBatch(bufferedImages,gifDirectory,gifFormatName,printPath,jarPath);
        System.out.println("整体耗时："+(System.currentTimeMillis()-start));
        System.out.println("========================printPath====================");
        System.out.println(printPath.toString());
        System.out.println("========================jarPath====================");
        System.out.println(jarPath.toString());
    }

}